/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
│ vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                   :vi │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2025 Justine Alexandra Roberts Tunney                              │
│                                                                              │
│ Permission to use, copy, modify, and/or distribute this software for         │
│ any purpose with or without fee is hereby granted, provided that the         │
│ above copyright notice and this permission notice appear in all copies.      │
│                                                                              │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
│ PERFORMANCE OF THIS SOFTWARE.                                                │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/dce.h"
#include "libc/macros.h"

//	define __get_tls() impl for each kind of assembly opcode
//	that -mno-tls-direct-seg-refs can generate. you must use
//	-mno-red-zone too. see tool/build/fixupobj.c which fixes
//	the object code generated by gcc to call these functions

	.macro	define_tls_getter name:req reg64:req reg32:req section:req
	.section \section,"ax",@progbits
	.align	16
\name:	mov	__hostos(%rip),%\reg32
	test	$_HOSTWINDOWS|_HOSTXNU,%\reg32
	jnz	1f
	mov	%fs:0x30,%\reg64 // Linux, FreeBSD, OpenBSD, NetBSD
	ret
1:	test	$_HOSTWINDOWS,%\reg32
	jnz	1f
	mov	%gs:0x30,%\reg64 // XNU
	ret
1:	mov	__tls_index(%rip),%\reg32	// Windows
	mov	%gs:0x1480(,%\reg64,8),%\reg64	// Hooray!
	ret
	.endfn	\name,globl
	.endm

	define_tls_getter __get_tls_rax rax eax  .privileged
	define_tls_getter __get_tls_rbx rbx ebx  .privileged.__get_tls_rbx
	define_tls_getter __get_tls_rcx rcx ecx  .privileged.__get_tls_rcx
	define_tls_getter __get_tls_rdx rdx edx  .privileged.__get_tls_rdx
	define_tls_getter __get_tls_rdi rdi edi  .privileged.__get_tls_rdi
	define_tls_getter __get_tls_rsi rsi esi  .privileged.__get_tls_rsi
	define_tls_getter __get_tls_rbp rbp ebp  .privileged.__get_tls_rbp
	define_tls_getter __get_tls_r8  r8  r8d  .privileged.__get_tls_r8
	define_tls_getter __get_tls_r9  r9  r9d  .privileged.__get_tls_r9
	define_tls_getter __get_tls_r10 r10 r10d .privileged.__get_tls_r10
	define_tls_getter __get_tls_r11 r11 r11d .privileged.__get_tls_r11
	define_tls_getter __get_tls_r12 r12 r12d .privileged.__get_tls_r12
	define_tls_getter __get_tls_r13 r13 r13d .privileged.__get_tls_r13
	define_tls_getter __get_tls_r14 r14 r14d .privileged.__get_tls_r14
	define_tls_getter __get_tls_r15 r15 r15d .privileged.__get_tls_r15

	.macro	define_tls_adder name:req reg64:req tmp64:req tmp32:req
	.section .privileged.\name,"ax",@progbits
	.align	16
\name:	testb	$_HOSTWINDOWS|_HOSTXNU,__hostos(%rip)
	jnz	1f
	add	%fs:0x30,%\reg64 // Linux, FreeBSD, OpenBSD, NetBSD
	ret
1:	testb	$_HOSTWINDOWS,__hostos(%rip)
	jnz	1f
	add	%gs:0x30,%\reg64 // XNU
	ret
1:	push	%\tmp64
	mov	__tls_index(%rip),%\tmp32	// Windows
	add	%gs:0x1480(,%\tmp64,8),%\reg64	// Hooray!
	pop	%\tmp64
	ret
	.endfn	\name,globl
	.endm

	define_tls_adder __add_tls_rax rax rcx ecx
	define_tls_adder __add_tls_rbx rbx rax eax
	define_tls_adder __add_tls_rcx rcx rax eax
	define_tls_adder __add_tls_rdx rdx rax eax
	define_tls_adder __add_tls_rdi rdi rax eax
	define_tls_adder __add_tls_rsi rsi rax eax
	define_tls_adder __add_tls_rbp rbp rax eax
	define_tls_adder __add_tls_r8  r8  rax eax
	define_tls_adder __add_tls_r9  r9  rax eax
	define_tls_adder __add_tls_r10 r10 rax eax
	define_tls_adder __add_tls_r11 r11 rax eax
	define_tls_adder __add_tls_r12 r12 rax eax
	define_tls_adder __add_tls_r13 r13 rax eax
	define_tls_adder __add_tls_r14 r14 rax eax
	define_tls_adder __add_tls_r15 r15 rax eax
